/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package prototype.runtime.federate.interactions;

import hla.rti.ArrayIndexOutOfBounds;
import hla.rti.RTIinternalError;
import hla.rti.ReceivedInteraction;
import hla.rti.SuppliedParameters;
import hla.rti.jlc.EncodingHelpers;
import hla.rti.jlc.RtiFactoryFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import prototype.persistence.pojo.Position;
import prototype.persistence.pojo.UserHasUnit;
import prototype.runtime.federate.RuntimeUser;
import prototype.runtime.interfaces.RuntimeUnit;

/**
 *
 * @author Server
 */
public class Fire {

    private int unitId;
    private Position position;
    private int power;
    private int radius;

    public Fire() {
        position = new Position();
    }

    public Fire(ReceivedInteraction theInteraction) throws ArrayIndexOutOfBounds {
        position = new Position();
        unitId = EncodingHelpers.decodeInt(theInteraction.getValue(0));
        position.setX(EncodingHelpers.decodeInt(theInteraction.getValue(1)));
        position.setY(EncodingHelpers.decodeInt(theInteraction.getValue(2)));
        position.setZ(EncodingHelpers.decodeInt(theInteraction.getValue(3)));
        power = EncodingHelpers.decodeInt(theInteraction.getValue(4));
        radius = EncodingHelpers.decodeInt(theInteraction.getValue(5));
    }

    public SuppliedParameters getParameters(int unitH, int posXH,
            int posYH, int posZH, int powerH, int radiusH) throws RTIinternalError {
        SuppliedParameters parameters =
                RtiFactoryFactory.getRtiFactory().
                createSuppliedParameters();
        parameters.add(unitH, EncodingHelpers.encodeInt(unitId));
        parameters.add(posXH, EncodingHelpers.encodeInt(position.getX()));
        parameters.add(posYH, EncodingHelpers.encodeInt(position.getY()));
        parameters.add(posZH, EncodingHelpers.encodeInt(position.getZ()));
        parameters.add(powerH, EncodingHelpers.encodeInt(power));
        parameters.add(radiusH, EncodingHelpers.encodeInt(radius));
        return parameters;
    }

    public Vector<Death> applyToUnit(List<RuntimeUnit> units) {
        Vector<Death> deaths = new Vector<Death>();
        for (int i = 0, size = units.size(); i < size; i++) {
            RuntimeUnit unit = units.get(i);
            UserHasUnit uhu = unit.getUnit();
            int distance, damage;
            if(uhu.getUnit().getHealth() < 0 ) {
                continue;
            }

            //calculate distance
            distance = findDistance(uhu.getPosition());
            if (radius == 0) {
                //if distance is not 0 then no hit
                damage = distance == 0 ? power : 0;
            } else {
                //reduce effect of the fire as distance increases
                damage = (int) (power * (1 - (double) distance / radius));
            }
            //reduce armor points
            damage -= uhu.getUnit().getArmor();
            if (damage > 0) {
                uhu.getUnit().setHealth(uhu.getUnit().getHealth() - damage);
                System.out.println("Unit " + uhu.getUnit().getName()
                        + " is hit with " + damage + " damage.\nRemaining health: "
                        + uhu.getUnit().getHealth());
                if (uhu.getUnit().getHealth() <= 0) {
                    uhu.getUnit().setName(uhu.getUnit().getName() + " - Dead");
                    deaths.add(new Death(uhu.getId()));
                }
            }
        }
        return deaths;
    }

    /**
     * @param pos
     * @return distance between pos and position of fire in 3D space
     */
    public int findDistance(Position pos) {
        double length;

        length = Math.pow(pos.getX() - position.getX(), 2);
        length += Math.pow(pos.getY() - position.getY(), 2);
        length += Math.pow(pos.getZ() - position.getZ(), 2);

        return (int) Math.sqrt(length);
    }

    public Position getPosition() {
        return position;


    }

    public void setPosition(Position position) {
        this.position = position;


    }

    public int getPower() {
        return power;


    }

    public void setPower(int power) {
        this.power = power;


    }

    public int getRadius() {
        return radius;


    }

    public void setRadius(int radius) {
        this.radius = radius;


    }

    public int getUnitId() {
        return unitId;


    }

    public void setUnitId(int unitId) {
        this.unitId = unitId;

    }
}
